﻿/*****************************************介绍*****************************************
 * 作者：Ywh
 * 创建时间：2024-06-08 09:43:28
 * 功能：框架管理器
 *      1、负责框架的初始化
 *      2、负责框架的清理
**************************************************************************************/

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEngine;

namespace Game.Framework
{
    public class FrameworkManager : BaseManager<FrameworkManager>
    {
        private LinkedList<IModule> m_Modules;
        private float m_InternalModuleProgress;
        private float m_CustomModuleProgress;
        private Type[] m_ModuleTypes;

        private FrameworkManager()
        {
            m_Modules = new LinkedList<IModule>();
            var assembly = Assembly.GetExecutingAssembly();
            m_ModuleTypes = assembly.GetTypes().Where(t => typeof(IModule).IsAssignableFrom(t) && !t.IsInterface).ToArray();
            CreateModules();
        }

        private void CreateModules()
        {
            SortedDictionary<int, IModule> allModule = new SortedDictionary<int, IModule>();
            // 创建模块
            foreach (var type in m_ModuleTypes)
            {
                var att = type.GetCustomAttribute<InternalModuleAttribute>();
                if (att == null) continue;

                var prop = type.BaseType.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public);
                if (prop != null)
                {
                    IModule module = prop.GetValue(null) as IModule;
                    allModule.Add(att.order, module);
                    LogManager.Log($"name:{type.Name} order:{att.order}", "Framwork", "Create");
                }
            }

            foreach (var module in allModule.Values)
                m_Modules.AddLast(module);
        }

        private SortedDictionary<int, IModule> CreateCustomModules()
        {
            SortedDictionary<int, IModule> result = new SortedDictionary<int, IModule>();
            // 创建模块
            foreach (var type in m_ModuleTypes)
            {
                var att = type.GetCustomAttribute<CustomModuleAttribute>();
                if (att == null) continue;
                var prop = type.BaseType.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public);
                if (prop != null)
                {
                    IModule module = prop.GetValue(null) as IModule;
                    result.Add(att.order, module);
                    LogManager.Log($"name:{type.Name} order:{att.order}", "Framwork", "Create");
                }
            }

            return result;
        }

        /// <summary>初始化</summary>
        public IEnumerator Init(Action<float> callback = null)
        {
            // 初始化模块
            var node = m_Modules.First;
            float index = 0;
            while (node != null)
            {
                node.Value.Init();
                while (node.Value.GetInitResult().type != E_ResultType.Success)
                {
                    var result = node.Value.GetInitResult();
                    switch (result.type)
                    {
                        case E_ResultType.Waiting:
                            LogManager.Log($"initing，type:{node.Value.GetType().Name}", "Framework", "Init");
                            break;
                        case E_ResultType.Fail:
                            throw new Exception(result.ToString());
                    }
                    yield return null;
                }

                LogManager.Log($"init success，type:{node.Value.GetType().Name}", "Framework", "Init");
                m_InternalModuleProgress = ++index / m_Modules.Count;
                callback?.Invoke(m_InternalModuleProgress);
                node = node.Next;
                yield return new WaitForSeconds(0.1f);
            }
            LogManager.Log($"<color=green>init framework internal modules success</color>", "Framework", "Init");

            // 初始化其他自定义模块
            var customModules = CreateCustomModules();
            float index2 = 0;
            foreach (var module in customModules.Values)
            {
                module.Init();
                while (module.GetInitResult().type != E_ResultType.Success)
                {
                    var result = module.GetInitResult();
                    switch (result.type)
                    {
                        case E_ResultType.Waiting:
                            LogManager.Log($"initing，type:{module.GetType().Name}", "Framework", "Init");
                            break;
                        case E_ResultType.Fail:
                            LogManager.LogError(result, "Framework", "Init");
                            yield break;
                    }
                    yield return null;
                }
                m_Modules.AddLast(module);
                yield return new WaitForSeconds(0.1f);
                m_CustomModuleProgress = ++index2 / customModules.Count;
                if (m_CustomModuleProgress >= 1) LogManager.Log($"<color=green>init framework custom modules success</color>", "Framework", "Init");
                CustomMuduleInitProgressEvent?.Invoke(m_CustomModuleProgress);
            }

            m_ModuleTypes = null;
        }

        /// <summary>清理框架内部所有模块</summary>
        public void Clear()
        {
            m_InternalModuleProgress = 0;
            m_CustomModuleProgress = 0;
            var node = m_Modules.Last;
            while (node != null)
            {
                node.Value.Clear();
                LogManager.Log($"clear success，moduleName:{node.Value.GetType().Name}", "Framework", "Clear");
                node = node.Previous;
            }
            m_Modules.Clear();
            CustomMuduleInitProgressEvent = null;
        }

        /// <summary>初始化进度</summary>
        public float InternalProgress => m_InternalModuleProgress;

        public float CustomProgress => m_CustomModuleProgress;

        public event Action<float> CustomMuduleInitProgressEvent;
    }
}